﻿using System;
using System.Threading;
using System.Windows.Forms;
using SevenZip;
using System.IO;
using System.Text;
using __ts.Core.Package;

namespace CCU.PackageBuilder
{
    public partial class FormMain : Form
    {
        delegate void SetProgressDelegate(ProgressEventArgs args);
        delegate void SetFileNameDelegate(FileNameEventArgs args);
        delegate void SetNoArgsDelegate();
        delegate void SetSettings(SevenZipCompressor compr);

        public FormMain()
        {
            InitializeComponent();
        }

        private void b_Browse_Click(object sender, EventArgs e)
        {
            if (fbd_Directory.ShowDialog() == DialogResult.OK)
            {
                tb_CompressDirectory.Text = fbd_Directory.SelectedPath;
            }
        }

        private void b_BrowseOut_Click(object sender, EventArgs e)
        {
            if (fbd_Directory.ShowDialog() == DialogResult.OK)
            {
                tb_CompressOutput.Text = fbd_Directory.SelectedPath;
            }
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
            // default values
            this.tb_CompressDirectory.Text = "D:\\CCU";
            this.tb_CompressOutput.Text = "D:\\CCU_Publish";
            this.tbFileName.Text = string.Format("CCU_(version)_{0}.ddt", DateTime.Now.ToString("yyyyMMdd"));
            this.tbExDir.Text = "D:\\CCU";
        }

        private void b_Compress_Click(object sender, EventArgs e)
        {
            if (dataGridView1.Rows.Count > 0)
            {
                pb_CompressWork.Style = ProgressBarStyle.Marquee;
                Thread worker = new Thread(new ThreadStart(Compress));
                worker.Start();
            }
            else
            {
                MessageBox.Show("必须添加至少一个源和解压目录。");
            }
        }

        void cmp_Compressing(object sender, ProgressEventArgs e)
        {
            pb_CompressProgress.Invoke(new SetProgressDelegate((args) =>
            {
                pb_CompressProgress.Increment(args.PercentDelta);
            }), e);
        }

        void cmp_FileCompressionStarted(object sender, FileNameEventArgs e)
        {
            l_CompressProgress.Invoke(new SetFileNameDelegate((args) =>
            {
                l_CompressProgress.Text = String.Format("Compressing \"{0}\"", e.FileName);
            }), e);
        }

        void cmp_CompressionFinished(object sender, EventArgs e)
        {
            l_CompressProgress.Invoke(new SetNoArgsDelegate(() =>
            {
                l_CompressProgress.Text = "Finished";
                pb_CompressWork.Style = ProgressBarStyle.Blocks;
                pb_CompressProgress.Value = 0;
            }));
        }

        private void Compress()
        {
            PackageCompressor pker = new PackageCompressor();
            SevenZipCompressor.SetLibraryPath(@"7z.dll");
            SevenZipCompressor cmp = new SevenZipCompressor();
            cmp.Compressing += new EventHandler<ProgressEventArgs>(cmp_Compressing);
            cmp.FileCompressionStarted += new EventHandler<FileNameEventArgs>(cmp_FileCompressionStarted);
            cmp.CompressionFinished += new EventHandler(cmp_CompressionFinished);
            this.Invoke(new SetSettings((compressor) =>
            {
                compressor.ArchiveFormat = OutArchiveFormat.SevenZip;
                compressor.CompressionLevel = CompressionLevel.Normal;
                compressor.CompressionMethod = CompressionMethod.Default;
                compressor.VolumeSize = 0;
            }), cmp);

            string archFileName = "";
            this.Invoke(new SetNoArgsDelegate(() =>
            {
                archFileName = tb_CompressOutput.Text.Trim(new char[] { '\\', '/' }) + "\\" + tbFileName.Text.Trim();
            }));

            for (int i = 0; i < dataGridView1.Rows.Count; i++)
            {
                DataGridViewRow r = dataGridView1.Rows[i];

                string directory = "";
                this.Invoke(new SetNoArgsDelegate(() =>
                {
                    directory = r.Cells[0].Value.ToString().Trim(new char[] { '\\', '/' });
                }));

                if (i == 0)
                    cmp.CompressionMode = CompressionMode.Create;
                else
                    cmp.CompressionMode = CompressionMode.Append;

                cmp.PreserveDirectoryRoot = true;
                pker.CompressDirectory(cmp, directory, archFileName);
            }

            addDefaultFile(cmp, archFileName, cmp.TempFolderPath + "extractBefore.bat", tbBefore.Text);
            addDefaultFile(cmp, archFileName, cmp.TempFolderPath + "extractAfter.bat", tbAfter.Text);
            addDefaultFile(cmp, archFileName, cmp.TempFolderPath + "package.xml", buildConfigXML());
        }

        private string buildConfigXML()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<packageConfigs>\r\n")
                .Append("<extractpath>\r\n");

            for (int i = 0; i < dataGridView1.Rows.Count; i++)
            {
                string dir = Path.GetFileName(dataGridView1.Rows[i].Cells[0].Value.ToString());
                string dir2 = dataGridView1.Rows[i].Cells[1].Value.ToString();
                sb.Append(@"<")
                    .Append(dir)
                    .Append(">")
                    .Append(dir2)
                    .Append("</")
                    .Append(dir)
                    .Append(">\r\n");
            }
            sb.Append("</extractpath>\r\n")
            .Append("</packageConfigs>");

            return sb.ToString();
        }

        private void addDefaultFile(SevenZipCompressor cmp, string archFileName, string filePath, string content)
        {
            FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
            StreamWriter sw = new StreamWriter(fs, Encoding.Default);
            sw.Write(content);
            sw.Flush();
            sw.Dispose();
            cmp.CompressionMode = CompressionMode.Append;
            new PackageCompressor().CompressFilesEncrypted(cmp, archFileName, filePath);
        }

        private void btnDirAdd_Click(object sender, EventArgs e)
        {
            dataGridView1.Rows.Add(new string[] { tb_CompressDirectory.Text.Trim(), tbExDir.Text.Trim() });
        }

        private void button1_Click(object sender, EventArgs e)
        {
            dataGridView1.Rows.Clear();
        }
    }
}
